#!usr/bin/python
# -*- coding:utf-8 -*-

import logging
import datetime
import sys
import traceback
import decimal
import socket
import getpass

from base.func.email import Email

PyLog_INFO = 0
PyLog_DEBUG = 1
PyLog_ERROR =2

class PyLog(object):
    """
    PyLog只是logging的空壳，本质是log按logname的全局字典
    PyLog多次实例化同一个logname的logger不影响log全局字典
    即：多次PyLog("raft").loginit(DEBUG)只有一个的log
    """
    INFO = logging.INFO
    DEBUG = logging.DEBUG
    ERROR = logging.ERROR
    WARN = logging.WARN

    __LOG_LIST = {}
    __LOG_ERREXIT = True
    __LOG_LASTERR = None
    PyLog = None
    MAILURL =None

    @staticmethod
    def loglist():
        return logging.manager.loggerDict

    @staticmethod
    def logget(logname):
        return PyLog.__LOG_LIST.get(logname)

    @staticmethod
    def logexit(errexit=True):
        PyLog.__LOG_ERREXIT = errexit

    def __init__(self,logname='raft',logpack=None):
        try:
            self.logger = logging.getLogger(logname)
            self.logname = logname
            if not logname in PyLog.__LOG_LIST:
                PyLog.__LOG_LIST.update({logname:self.logger})
            self.logpack =None
            if logpack:
                self.logpack = self.__get_pack(logpack)
            PyLog.PyLog = self
            self.lasterr = ''
        except Exception as e:
            traceback.print_exc()
            print(e)

    def __get_pack(self,logpack):
        pos = logpack.find("site-packages")
        pos = pos + 14 if pos>0 else logpack.find("labsight")
        pack = logpack[pos:]
        return pack[0:pack.rfind(".")].replace("\\",'/').replace("/",".")

    def __get_info(self,info,infile,withpack=True):
        if withpack:
            if self.logpack:
                return "[%s]%s" % (self.logpack,info)
            elif infile:
                pack = self.__get_pack(infile)
                return "[%s]%s" % (pack,info)
        return info

    def loginit(self,loglevel=logging.INFO,logpath=None,writefile=True,writestream=True):
        try:
            self.logger.setLevel(loglevel)
            if self.logger.handlers:
                return self
            if writefile and logpath:
                self.logpath = logpath
                fh = logging.FileHandler(logpath,encoding='utf8')
                fh.setLevel(loglevel)
                logformat = '%(asctime)s %(levelname)s:%(message)s'
                formatter = logging.Formatter(logformat)
                fh.setFormatter(formatter)
                self.logger.addHandler(fh)
            if writestream:
                ch = logging.StreamHandler()
                ch.setLevel(loglevel)
                logformat = '[ %(levelname)s %(asctime)s ]:%(message)s'
                formatter=logging.Formatter(logformat)
                ch.setFormatter(formatter)
                self.logger.addHandler(ch)
            return self
        except Exception as e:
            traceback.print_exc()
            print()

    def loglevel(self,level):
        """扩展level定义，减少log包及全局变量的导入"""
        try:
            if int(level) == PyLog_DEBUG or int(level) == logging.DEBUG:
                self.logger.setLevel(logging.DEBUG)
            elif int(level) == PyLog_ERROR or int (level) == logging.ERROR:
                self.logger.setLevel(logging.ERROR)
            else:
                self.logger.setLevel(logging.INFO)
        except Exception as e:
            traceback.print_exc()
            print(e)

    def getlevel(self):
        return self.logger.level

    def isdebug(self):
        return self.logger.isEnabledFor(logging.DEBUG)

    def info(self,info,infile=None,withpack=True):
        try:
            if not info:return
            if isinstance(info,dict):
                for(k,v) in info.items():
                    if isinstance(v,str) or isinstance(v,int):
                        self.logger.info("%-s*:%s" % (25,k,v))
                    elif v and not isinstance(v,PyLog):
                        self.info("%s>>>" % (k),infile,withpack=withpack)
                        self.info(v,infile,withpack=withpack)
            elif isinstance(info,list):
                for item in info:
                    self.info(item,infile,withpack=withpack)
            elif not isinstance(info,PyLog):
                self.logger.info(self.__get_info(info,infile,withpack=withpack))
        except Exception as e:
            self.logger.debug(e)

    def debug(self,info,infile=None,withpack=False):
        try:
            if not info:return
            if not self.logger.isEnabledFor(logging.DEBUG):return
            if isinstance(info,dict):
                for (k,v) in info.items():
                    if v is None:
                        self.logger.info("%-s*:%s" % (25, k, v))
                    elif isinstance(v,list):
                        self.logger.info("%-s*:%s" % (25, k, v))
                    elif isinstance(v,decimal.Decimal):
                        self.logger.info("%-s*:%s" % (25, k, v))
                    elif isinstance(v,datetime.datetime):
                        self.logger.info("%-s*:%s" % (25, k, v))
                    elif isinstance(v,str) or isinstance(v,int) or isinstance(v,float):
                        self.logger.info("%-s*:%s" % (25, k, v))
                    elif v and not isinstance(v,PyLog):
                        self.debug("%s" % (k),infile,withpack=False)
                        self.debug(v,infile,withpack=False)
            elif isinstance(info,list):
                for item in info:
                    self.debug(item,infile,withpack)
            elif not isinstance(info,PyLog):
                self.logger.debug(self.__get_info(info,infile,withpack))
        except Exception as e:
            pass

    def warn(self,info,infile=None,withpack=True):
        try:
            self.logger.warning(self.__get_info(info,infile,withpack))
        except Exception as e:
            self.logger.debug(e)

    def err(self,info,infile=None,withpack=True,sysexit=True):
        try:
            errinfo=[]
            errinfo.append('\n[ ERROR_From ]:'+ getpass.getuser() + '@' +socket.gethostname())
            errinfo.append('[ ERROR_Shell ]:' + ' '.join(sys.argv))
            errinfo.append('[ ERROR_Error ]:%s' % self.__get_info(info,infile,withpack))
            tb = sys.exc_info()[2]
            if tb:
                tbinfo = "[ ERROR_FTraceback ]:"
                for i in traceback.extract_tb(tb):
                    tbinfo+="File \"%s\" line %s in %s:<br>\n" % (i[0],i[1],i[2])
                    tbinfo+="    " +i[3]
                errinfo.append(tbinfo)
            PyLog.__LOG_LASTERR = errinfo
            self.logger.error('\n'.join(errinfo))
            if 'errmail' in sys.argv:
                self.sendmail(errinfo[2],'<b><br>'.join([i + '<b><br>' for i in errinfo]))
            if PyLog.__LOG_ERREXIT and sysexit:
                self.logger.info("pysail forced exit!!!!!!!!")
                sys.exit(1)
        except Exception as e:
            self.logger.debug(e)

    def error(self,info,infile=None,withpack=True,sysexit=True):
        """兼容性空壳"""
        self.err(info,infile,withpack,sysexit)

    def logtext(self,info,level=logging.INFO,infile=None,withpack=True):
        if level ==logging.INFO:
            self.info(info,infile,withpack)
        elif level==logging.WARN:
            self.warn(info,infile,withpack)
        elif level == logging.ERROR:
            self.err(info,infile,withpack)
        else:
            self.debug(info,infile,withpack)

    def exit(self,info,infile=None,withpack=True):
        try:
            tb=sys.exc_info()[2]
            if tb:
                errinfo = "Traceback (most recent call last):\n"
                for i in traceback.extract_tb(tb):
                    errinfo += "File \"%s\" line %s in %s:\n" % (i[0],i[1],i[2])
                    errinfo += "    " + i[3]
                self.logger.error(self.__get_info(errinfo,infile))
            self.logger.error(self.__get_info(info,infile,withpack))
            sys.exit(1)
        except Exception as e:
            self.log.warn(e)

    def welcome(self,module=None,workpath=None,conf = None,args=None):
        lenline,title = 60,"Labsight"
        self.info("=" * 60)
        self.info("%s%s" % (" " * int((60-len(title))/2),title))
        self.info("=" * 60)
        if module:
            self.debug("blugin     =%s" %module)
            self.info("workpath   =%s" % workpath)
            self.info("conf       =%s" % conf)
            self.info("args       =%s" % args)
            self.info("-" * 60)

    def goodbye(self):
        self.info("%sgoodbye%s" % ("=" * 30,"=" * 30))

    def getlasterr(self):
        return PyLog.__LOG_LASTERR

    def sendmail(self,subject,info):
        return Email(self).sendemail(subject, info)